import java.util.concurrent.*;

/**
 * @author 3489309323@qq.com
 * @create 2020-09-14-18:51
 */
public class TreadTest {
  /**
   * 多线程测试时 不能用测试类(@Test)
   *
   * 这样测试不出多线程效果
   *
   */
  //①
  /*public static void main(String[] args) {
    System.out.println("main...start...");

    //1)、 方式一: 继承Thread
    Thread01 thread01 = new Thread01();
    thread01.start(); //启动一个线程去执行线程示例的run方法 //接下来不会等待线程执行完再往下执行代码 会直接执行

    //2)、 方式二: 实现Runnable接口
    //3)、 方式三: 实现Callable接口 + FutureTask(可以拿到返回结果,可以处理异常)
    //4)、 线程池

    System.out.println("main...end...");

//    main...start...
//    main...end...
//    当前线程id: 22
//    运行结果: 5
  }*/

  //②
  /*public static void main(String[] args) {
    System.out.println("main...start...");

    //1)、 方式一: 继承Thread
    //2)、 方式二: 实现Runnable接口
    Runable01 runable01 = new Runable01();
    Thread thread02 = new Thread(runable01);
    thread02.start(); //接下来不会等待线程执行完再往下执行代码 会直接执行
    //3)、 方式三: 实现Callable接口 + FutureTask(可以拿到返回结果,可以处理异常)
    //4)、 线程池

    System.out.println("main...end...");

//    main...start...
//    main...end...
//    当前线程id: 22
//    运行结果: 5
  }*/

  //③
  /*public static void main(String[] args) throws ExecutionException, InterruptedException {
    System.out.println("main...start...");

    //1)、 方式一: 继承Thread
    //2)、 方式二: 实现Runnable接口
    //3)、 方式三: 实现Callable接口 + FutureTask(可以拿到返回结果,可以处理异常)
    FutureTask<Integer> integerFutureTask = new FutureTask<>(new Callable01()); //也可以传runnable,并且也可以有返回值,通过public FutureTask(Runnable runnable, V result)
    Thread thread03 = new Thread(integerFutureTask);
    thread03.start();

    //等待整个线程执行完成获取返回结果
    //So 这里会阻塞,也就说会先打印  "拿到返回结果: 5" 再打印 "main...end..."
    Integer integer = integerFutureTask.get();

    System.out.println("拿到返回结果: " + integer);
    //4)、 线程池

    System.out.println("main...end...");

//    main...start...
//    当前线程id: 22
//    运行结果: 5
//    拿到返回结果: 5
//    main...end...
  }*/


  //④
  //以上三种启动线程的方式都不用,我们最好使用线程池的方式,这样有助于控制资源,保证系统稳定(堆空间栈空间都是有限的,如果不做控制,会导致资源耗尽系统崩溃)

  //注意:
  //1. 不应该是执行每一个异步任务就上来创建一个池,而是我们整个系统一个线程池
  public static ExecutorService service = Executors.newFixedThreadPool(10);

  public static void main(String[] args) throws ExecutionException, InterruptedException {
    System.out.println("main...start...");

    //1)、 方式一: 继承Thread
    //2)、 方式二: 实现Runnable接口
    //3)、 方式三: 实现Callable接口 + FutureTask(可以拿到返回结果,可以处理异常)
    //4)、 线程池
    service.execute(new Runable01());

    System.out.println("main...end...");

//    main...start...
//    main...end...
//    当前线程id: 22
//    运行结果: 5
  }

  public static class Thread01 extends Thread {
    @Override
    public void run(){
      System.out.println("当前线程id: " + Thread.currentThread().getId());
      int i = 10 / 2;
      System.out.println("运行结果: " + i);
    }
  }

  public static class Runable01 implements Runnable {
    @Override
    public void run(){
      System.out.println("当前线程id: " + Thread.currentThread().getId());
      int i = 10 / 2;
      System.out.println("运行结果: " + i);
    }
  }

  public static class Callable01 implements Callable<Integer/*←返回结果类型*/>{

    @Override
    public Integer call() throws Exception {
      System.out.println("当前线程id: " + Thread.currentThread().getId());
      int i = 10 / 2;
      System.out.println("运行结果: " + i);
      return i;
    }
  }
}
